#include<stdio.h>
#include<time.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<memory.h>
 
/*定义矩阵中元素的上限，避免相乘后溢出*/
#define RANGE 100
/*矩阵A有M行N列，矩阵B有N行M列*/
#define M 1000
#define N 1000
#define P 500
int pthred_count=8; 
void gene_matrix();
void read_matrix();
void *a11_b11();//1
void *a12_b21();//2
void *a11_b12();//3
void *a12_b22();//4
void *a21_b11();//5
void *a22_b21();//6
void *a21_b12();//7
void *a22_b22();//8
void output_result();
int matrixA[M][N];
int matrixB[N][M];
int matrixResult1[M][N]={0};
int matrixResult2[M][N]={0};
 
//int arr[pthred_count][M][N];
void *func(void *arg);
 
int main()
{
	
    gene_matrix();                                      //用随机数产生两个待相乘的矩阵，并分别存入两个文件中
    read_matrix();                                      //从两个文件中读出数据赋给matrixA和matrixB
    clock_t start=clock();                              //开始计时
    int res[M][N]={0};                                  //保存矩阵相乘的结果。非全局变量一定要显示初始化为0,否则为随机的一个数
    int i=0,j,k;
	pthread_t tids[8];
	pthread_create(&tids[0],NULL,a11_b11,NULL);
	pthread_create(&tids[1],NULL,a12_b21,NULL);
	pthread_create(&tids[2],NULL,a11_b12,NULL);
	pthread_create(&tids[3],NULL,a12_b22,NULL);
	pthread_create(&tids[4],NULL,a21_b11,NULL);
	pthread_create(&tids[5],NULL,a22_b21,NULL);
	pthread_create(&tids[6],NULL,a21_b12,NULL);
	pthread_create(&tids[7],NULL,a22_b22,NULL);
    for(i=0;i<8;i++)
        pthread_join(tids[i],NULL);                         //合之前一定要等所有的子线程计算结束
    
	int ii,jj;	
	for(ii=0;ii<M;ii++)
		for(jj=0;jj<N;jj++)
			  matrixResult1[ii][jj]+=matrixResult2[ii][jj];
	         
	//output_result();				//输出最后的计算结果
    clock_t finish=clock();         //结束计算时的时间
    printf("time is %.2f seconds\n",(long)(finish-start)/1E6);
    return 0;
}
 
//下面的八个函数分别计算两个矩阵相乘时的每一个块
void *a11_b11()//1
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult1[i][j]+=matrixA[i][k]*matrixB[k][j];
}
void *a12_b21()//2
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult2[i][j]+=matrixA[i][k+P]*matrixB[k+P][j];
}
 
void *a11_b12()//3
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult1[i][j+P]+=matrixA[i][k]*matrixB[k][j+P];
}
void *a12_b22()//4
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult2[i][j+P]+=matrixA[i][k+P]*matrixB[k+P][j+P];
}
void *a21_b11()//5
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult1[i+P][j]+=matrixA[i+P][k]*matrixB[k][j];
}
void *a22_b21()//6
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult2[i+P][j]+=matrixA[i+P][k+P]*matrixB[k+P][j];
}
void *a21_b12()//7
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult1[i+P][j+P]+=matrixA[i+P][k]*matrixB[k][j+P];
}
void *a22_b22()//8
{
	int i,j,k;
	for(i=0;i<P;i++)
		for(j=0;j<P;j++)
			for(k=0;k<P;k++)
				matrixResult2[i+P][j+P]+=matrixA[i+P][k+P]*matrixB[k+P][j+P];
}
 
void gene_matrix()
{
    FILE *file1,*file2;
    if((file1=fopen("matrixA","w+"))==NULL)
    {
        perror("fopen");
        exit(1);
    }
    if((file2=fopen("matrixB","w+"))==NULL)
    {
        perror("fopen");
        exit(1);
    }
    int i,j;
    srand((unsigned)time(NULL));
    for(i=0;i<M;i++)
    {
        for(j=0;j<N;j++)
            fprintf(file1,"%-8d",rand()%RANGE);
        fprintf(file1,"\n");
    }
    fclose(file1);
    for(i=0;i<N;i++)
    {
        for(j=0;j<M;j++)
            fprintf(file2,"%-8d",rand()%RANGE);
        fprintf(file2,"\n");
    }
    fclose(file2);  
}
 
void read_matrix()
{
    FILE *file1,*file2;
    if((file1=fopen("matrixA","rt"))==NULL)
    {
        perror("fopen");
        exit(1);
    }
    if((file2=fopen("matrixB","rt"))==NULL)
    {
        perror("fopen");
        exit(1);
    }
    int i,j;
    for(i=0;i<M;i++)
        for(j=0;j<N;j++)
            fscanf(file1,"%d",&matrixA[i][j]);
    fclose(file1);
    for(i=0;i<N;i++)
        for(j=0;j<M;j++)
            fscanf(file2,"%d",&matrixB[i][j]);
    fclose(file2);
}
//输出最后的计算结果
void output_result()
{
	int ii,jj;
	for(ii=0;ii<M;ii++)
		{for(jj=0;jj<N;jj++)
			printf("%d ",matrixResult1[ii][jj]);
		printf("\n");} 
}